package cn.abcsys.cloud.devops.pipeline.core.impl;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.ConnectException;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSONObject;
import com.github.dockerjava.api.DockerClient;

import cn.abcsys.cloud.devops.pipeline.builder.RequestCommand;
import cn.abcsys.cloud.devops.pipeline.common.Common;
import cn.abcsys.cloud.devops.pipeline.common.Constant;
import cn.abcsys.cloud.devops.pipeline.common.ImageObject;
import cn.abcsys.cloud.devops.pipeline.common.SystemConfig;
import cn.abcsys.cloud.devops.pipeline.core.ImageCore;
import cn.abcsys.cloud.devops.pipeline.util.CommandExcutor;
import cn.abcsys.cloud.devops.pipeline.util.IOUtils;
import cn.abcsys.cloud.devops.pipeline.util.Result;
import cn.abcsys.cloud.devops.pipeline.util.SSH;
@Component
public class ImageCoreImpl implements ImageCore {
	protected DockerClient dockerClient;
	@Autowired
	private SystemConfig systemConfig;
	public Result makeImage(JSONObject paramIn){
		String targetFolder = paramIn.getString("jenkinsBuildPath");
		if(StringUtils.isEmpty(targetFolder)){
			targetFolder = ".";
		}
		String imageName = paramIn.getString("imageName");
		if(StringUtils.isEmpty(imageName)){
			imageName = paramIn.getString("jenkinsJobName");
		}
		if(!StringUtils.isEmpty(paramIn.getString("imageTag"))){
			imageName += ":"+paramIn.getString("imageTag");
		}
		SSH ssh = new SSH(paramIn.getString("pipelineHostIp"), 
				paramIn.getString("pipelineHostUser"), paramIn.getString("pipelineHostPwd"));
		String result = "";
		try {
			if(!StringUtils.isEmpty(paramIn.getString("Dockerfile"))&&ssh.connect()){
				try{
					ssh.execute(this.createDockerfileCommand(targetFolder,
							paramIn.getString("Dockerfile")));
				}finally {
					ssh.close();
				}
			}
			if(ssh.connect()){
				try{
					String commandLine = this.getBuildImageCommand( targetFolder, imageName);
					result = ssh.executeWithResult(commandLine);
					int index =result.indexOf("\n");
					if(index>0){
						result = result.substring(0, index);
					}
					
				}finally {
					ssh.close();
				}
			}
			Result imageIdObject = this.getImageIdByImageNameInPipeline(imageName);
			if(imageIdObject.isSuccess()){
				paramIn.put("imageUuid", imageIdObject.getData());
			}else{
				return imageIdObject;
			}
			paramIn.put("executeResult", result);
			return new Result(true, paramIn,"success");
		} catch (SocketException e) {
			return new Result(false, "make image error:"+e.getMessage());
		} catch (IOException e) {
			return new Result(false, "make image error:"+e.getMessage());
		}
	}
	/**
     * @param targetFolder
     * @param imageName
     * @param imageTag
     * @param image_uuid
     * @return 根据目标业务文件夹，生成制作镜像以及后续处理命令字符串
     */
    private String getBuildImageCommand(String targetFolder,String imageName) {
    	targetFolder.replace("//", "/");
        StringBuilder buildImageCommand = new StringBuilder();
        buildImageCommand
                .append("cd "+targetFolder+";docker build -t " + imageName + " .")
                .append(";");
        return buildImageCommand.toString();
    }
    /**
     * @param targetFolder
     * @param imageName
     * @param imageTag
     * @param image_uuid
     * @return 根据目标业务文件夹，生成制作的Dockerfile文件
     */
    private String createDockerfileCommand(String targetFolder,String Dockerfile) {
        StringBuilder createDockerfileCommand = new StringBuilder();
        createDockerfileCommand
                .append("cd " + targetFolder + (("").equals(targetFolder) ? "" : "/"))
                .append(";");
        createDockerfileCommand.append("echo "+Dockerfile+" > Dockerfile;");
        return createDockerfileCommand.toString();
    }
    @Override
    public Result scanImage(JSONObject paramIn) {
        SSH ssh = new SSH(paramIn.getString("pipelineHostIp"), 
				paramIn.getString("pipelineHostUser"), paramIn.getString("pipelineHostPwd"));
        StringBuffer sb = new StringBuffer();
        boolean flag = false;
        String imageUuid = paramIn.getString("imageUuid");
        try {
            if (ssh.connect()) {
                String scanCommand = "sh /usr/bin/scanner " + imageUuid + " > /tmp/scanner_result_" + imageUuid + ".txt 2>&1";
                String result = ssh.executeWithResult(scanCommand);
                ssh.close();
            }
            if (ssh.connect()) {
                //判断本机路径是否存在，不存在创建
                String imageClairLogsPath = paramIn.getString("imageClairLogsPath");
                IOUtils.createFile(imageClairLogsPath, "/scanner_result_" + imageUuid + ".txt");
                flag = ssh.fetchFile("/tmp/scanner_result_" + imageUuid + ".txt", imageClairLogsPath);
                if (flag) {
                    File file = new File(imageClairLogsPath + "/scanner_result_" + imageUuid + ".txt");
                    BufferedReader reader = null;
                    try {
                        reader = new BufferedReader(new FileReader(file));
                        String tempString = null;
                        int line = 1;
                        // 一次读入一行，直到读入null为文件结束
                        while ((tempString = reader.readLine()) != null) {
                            // 显示行号
                            sb.append(tempString + "\n");
                            line++;
                        }
                        reader.close();
                    } catch (IOException e) {
                        return new Result(false, "read scan file error:"+e.getMessage());
                    } finally {
                        if (reader != null) {
                            try {
                                reader.close();
                            } catch (IOException e) {
                            	return new Result(false, "read scan file error:"+e.getMessage());
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            return new Result(false, "Scan Images Error!"+e.getLocalizedMessage());
        } finally {
            ssh.close();
        }

        if (flag) {
            return new Result(true, sb.toString().replace("\n", "<br>"),"success");
        } else {
            return new Result(false, "Scan Images Error!Error during SCP transfer!No such file or directory!");
        }
    }

    @Override
    public Result showImageScanResult(JSONObject paramIn) {
    	String imageUuid = paramIn.getString("imageUuid");
    	String imageClairLogsPath = paramIn.getString("imageClairLogsPath");
        StringBuffer sb = new StringBuffer();
        File file = new File(imageClairLogsPath + "scanner_result_" + imageUuid + ".txt");
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader(file));
            String tempString = null;
            // 一次读入一行，直到读入null为文件结束
            while ((tempString = reader.readLine()) != null) {
                // 显示行号
                sb.append(tempString + "\n");
            }
            reader.close();
        } catch (IOException e) {
        	return new Result(false, "read scan file error:"+e.getMessage());
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                	return new Result(false, "read scan file error:"+e.getMessage());
                }
            }
        }
        return new Result(true, sb.toString().replace("\n", "<br>"));
    }
    
    @Override
    public Result pushImage(JSONObject paramIn) {
    	String ip = paramIn.getString("pipelineHostIp"); 
    	String name = paramIn.getString("pipelineHostUser"); 
    	String password = paramIn.getString("pipelineHostPwd");  
    	String imageName = paramIn.getString("imageName"); 
    	String imageTag = paramIn.getString("imageTag"); 
    	String registryUrl = paramIn.getString("registryUrl");
    	if(StringUtils.isEmpty(registryUrl)){
    		return new Result(false, "仓库地址不能为空");
    	}else{
    		registryUrl = registryUrl.replace("http://", "").replace("https://", "");
    		registryUrl = registryUrl.endsWith("/")?registryUrl.substring(0,registryUrl.lastIndexOf("/")):registryUrl;
    	}
        SSH ssh = CommandExcutor.getSsh(ip, name, password);
        try {
            if (ssh.connect()) {
                StringBuilder commandStr = new StringBuilder();
                commandStr.append("docker tag "+ imageName+":"+imageTag+" "+registryUrl+"/"+ imageName+":"+imageTag
                		+";docker push " + registryUrl+"/"+ imageName+":"+imageTag);
                try {
                    String result = ssh.executeWithResult(commandStr.toString());
                    if (result.contains("Error")||result.contains("error") || 
                    		result.contains("failed") || result.contains("EOF")) {
                        return new Result(false, "镜像发布脚本执行失败！");
                    } else if (result.contains("Cannot connect to the Docker daemon.")) {
                        return new Result(false, "【制作镜像失败】：仓库主机上的Docker服务异常！");
                    } else if (result.contains("refused")) {
                        return new Result(false, "仓库服务调用异常");
                    } else {
                        return new Result(true,result, "镜像发布成功！");
                    }
                } catch (Exception e) {
                    return new Result(false, "发布镜像失败：发布镜像脚本执行异常！");
                } 
            } else {
                return new Result(false, "镜像发布失败：连接仓库主机异常！");
            }
        } catch (Exception e) {
            return new Result(false, "镜像发布失败：SSH无法连接仓库主机！请检查主机运行状态、网络连接状态或核对输入正确的用户名和密码。");
        }finally {
            ssh.close();
        }
    }
    @Override
    public Result uploadImage(JSONObject paramIn){
    	String targetFolder = paramIn.getString("targetFolder");
    	String fileName = paramIn.getString("fileName");
    	String hostname = paramIn.getString("hostname");
    	String username = paramIn.getString("username");
    	String password = paramIn.getString("password");
    	SSH ssh = new SSH(hostname, username, password);
    	if (!fileName.endsWith(".tar")) {
            return new Result(false, "制作基础镜像异常：不支持此类文件(" + fileName + ")类型！");
        }
    	
    	
    	
    	//step1:检查tar文件是否存在,将repostories文件解析到本地
    	String step1_command = "cd "+targetFolder+";tar xvf "+fileName+" repositories 2&>1; ls repositories";
    	try{
    		if(ssh.connect()){
    			String fileExist = ssh.executeWithResult(step1_command);
    			if(!Constant.repositories.equals(fileExist.replaceAll("\n", ""))){
    				return new Result(false, "镜像文件解析异常，repositories文件不存在，可能不是正常的镜像包。");
    			}
    		}else{
    			return new Result(false, "SSH无法连接仓库主机！请检查主机运行状态、网络连接状态或核对输入正确的用户名和密码。");
    		}
    	}catch (Exception e) {
            return new Result(false, "镜像制作失败：SSH无法连接仓库主机！请检查主机运行状态、网络连接状态或核对输入正确的用户名和密码。");
        }finally {
    		ssh.close();
		}
    	//step2:读取repostories文件
    	String step2_command = "cat "+targetFolder+"/repositories";
    	List<ImageObject> imageObjects = new ArrayList<>();
    	try{
    		if(ssh.connect()){
    			String file_Stream = ssh.executeWithResult(step2_command);
    			if(StringUtils.isEmpty(file_Stream)){
    				return new Result(false, "镜像文件解析异常，repositories文件不存在，可能不是正常的镜像包。");
    			}
    			JSONObject repositories_json = JSONObject.parseObject(file_Stream);
    	    	Set<String> repositories_set = repositories_json.keySet();
    	    	Iterator<String> repositories_iterator = repositories_set.iterator();
    	    	while(repositories_iterator.hasNext()){
    	    		String imageName = repositories_iterator.next();
    	    		System.out.println("imageName:"+imageName);
    	    		JSONObject tag_json = JSONObject.parseObject(repositories_json.get(imageName).toString());
    	    		Set<String> tag_set = tag_json.keySet();
    	        	Iterator<String> tag_iterator = tag_set.iterator();
    	        	while(tag_iterator.hasNext()){
    	        		String imageTag = tag_iterator.next();
    	        		System.out.println("imageTag:"+imageTag);
    	        		System.out.println("imageUuid:"+tag_json.get(imageTag));
    	        		ImageObject imageObject = new ImageObject(imageName, imageTag, tag_json.get(imageTag).toString());
    	        		imageObjects.add(imageObject);
    	        	}
    	    	}
    		}else{
    			return new Result(false, "SSH无法连接仓库主机！请检查主机运行状态、网络连接状态或核对输入正确的用户名和密码。");
    		}
    	}catch (Exception e) {
            return new Result(false, "镜像制作失败：SSH无法连接仓库主机！请检查主机运行状态、网络连接状态或核对输入正确的用户名和密码。");
        }finally {
    		ssh.close();
		}
    	//setp3:上传镜像
//    	try{
//    		if(ssh.connect()){
//    			String fileExist = ssh.executeWithResult(step1_command);
//    			if(!Constant.repositories.equals(fileExist)){
//    				return new Result(false, "镜像文件解析异常，repositories文件不存在，可能不是正常的镜像包。");
//    			}
//    		}else{
//    			return new Result(false, "SSH无法连接仓库主机！请检查主机运行状态、网络连接状态或核对输入正确的用户名和密码。");
//    		}
//    	}catch (Exception e) {
//            return new Result(false, "镜像制作失败：SSH无法连接仓库主机！请检查主机运行状态、网络连接状态或核对输入正确的用户名和密码。");
//        }finally {
//    		ssh.close();
//		}
    	StringBuilder commandStr = new StringBuilder();
        if (fileName.endsWith(".tar")) {
            commandStr.append("docker load --input " + targetFolder + "/" + fileName + ";");
            /* 删除整个保存上传文件文件夹 */
            commandStr.append("rm -rf " + targetFolder + "/;");
        } else {
            return new Result(false, "制作基础镜像异常：不支持此类文件(" + fileName + ")类型！");
        }
        try {
            if (ssh.connect()) {
                String command = commandStr.toString();
                String result = ssh.executeWithResult(command.toString());
                Result re  = processMakeImageResult(result);
                if(!re.isSuccess()){
                	return re;
                }
                return new Result(true, imageObjects,"make image success");
            } else {
                return new Result(false, "SSH无法连接仓库主机！请检查主机运行状态、网络连接状态或核对输入正确的用户名和密码。");
            }
        } catch (Exception e) {
            return new Result(false, "镜像制作失败：SSH无法连接仓库主机！请检查主机运行状态、网络连接状态或核对输入正确的用户名和密码。");
        } finally {
            ssh.close();
        }
    }
    /**
     * @param basic
     * @param response
     * @return
     */
    private Result processMakeImageResult(String response) {
        if (response.contains("cannot find or open")) {
            return new Result(false, "【应用包解压失败】：应用文件压缩包不存在！可能被其他用户后台删除");
        } else if (response.contains("Cannot connect to the Docker daemon.")) {
            return new Result(false, "【制作镜像失败】：仓库主机上的Docker服务异常！");
            /** @bug219_begin:[镜像管理]制作镜像,当找不到文件夹或文件而制作失败,请将该错误原因返回给终端 **/
        } else if (response.toLowerCase().contains("no such file or directory")) {
            return new Result(false, "【制作镜像失败】：仓库主机上无法找到与制作镜像相关的文件或文件夹！");
        } else if (response.toLowerCase().contains("no such id")) {
            return new Result(false, "【制作镜像失败】：tag失败");
        } else if (response.toLowerCase().contains("Error")) {
            return new Result(false, "【制作镜像失败】：未知错误");
        }else{
        	return new Result(true, "");
        }
//        /** @bug219_finish **/
//        BufferedReader reader = new BufferedReader(
//                new InputStreamReader(new ByteArrayInputStream(response.getBytes())));
//        String uuid = null, imagesize = null;
//        try {
//            String line = null;
//            while ((line = reader.readLine()) != null) {
//                if (line.contains("IMAGE_ID")) {
//                    uuid = line.split(":")[1];
//                } else if (line.contains("IMAGE_SIZE")) {
//                    imagesize = line.split(":")[1];
//                } else {
//                    continue;
//                }
//            }
//        } catch (IOException e) {
//           return new Result(false, "解析返回值失败:"+e.getMessage());
//        } finally {
//            try {
//                reader.close();
//            } catch (IOException e) {
//                return new Result(false, "关闭数据流失败:"+e.getMessage());
//            }
//        }
//        if (null == uuid) {
//            return new Result(false, "上传执行异常，镜像制作失败！");
//        } else {
//            return new Result(true, uuid + ":" + imagesize);
//        }
    }

    /**
     * @Title: getImageIdByImageName 
     * @Description: 在CI主机上获取镜像id
     * @param @param imageName
     * @param @return    设定文件 
     * @return Result    返回类型 
     * @throws
      */
     @Override
     public Result getImageIdByImageNameInPipeline(String imageName){
     	String command = RequestCommand.getImageIdByImageNameCommand(imageName);
     	SSH ssh = new SSH(systemConfig.getPipelineHostIp(), 
     			systemConfig.getPipelineHostUser(), systemConfig.getPipelineHostPwd());
     	try {
     		if(ssh.connect()){
     			String imageIdstr = ssh.executeWithResult(command, Common.SSH_EXECUTE_LOW_OUT_TIME);
     			int index =imageIdstr.indexOf("\n");
				if(index>0){
					imageIdstr = imageIdstr.substring(0, index);
				}
     			if(!StringUtils.isEmpty(imageIdstr)){
     				String imageId = imageIdstr.substring(imageIdstr.indexOf(":")+1).replace("\n", "");
     				imageId = imageId.replaceAll(" ", "");
     				if(imageId.length()!=64){
     					return new Result(false, imageIdstr);
     				}
     				return new Result(true,imageId,"success");
     			}else{
     				return new Result(false, imageIdstr);
     			}
     		}else{
     			return new  Result(false, "查询镜像ID失败,SSH连接异常");
     		}
     	} catch (ConnectException e) {
     		return new Result(false, "查询镜像ID失败："+e.getMessage());
 		} catch (IOException e) {
 			return new Result(false, "查询镜像ID失败："+e.getMessage());
 		}finally {
			ssh.close();
		}
     }
}
